//+ref=联机版引用/Engine.dll
//+ref=联机版引用/EntitySystem.dll
//+ref=联机版引用/Survivalcraft.dll
using Engine;
using System;
using System.Collections.Generic;
using TemplatesDatabase;

namespace Game
{
    /// <summary>
    /// 双倍连锁采集子系统 - 实现破坏方块时的连锁采集效果
    /// </summary>
    public class SubsystemLiansuoBlockBehavior : SubsystemPollableBlockBehavior, IUpdateable
    {
        // 子系统引用
        public SubsystemTime m_subsystemTime;               // 游戏时间系统
        public SubsystemGameInfo m_subsystemGameInfo;      // 游戏信息系统
        public SubsystemPickables m_subsystemPickables;    // 可拾取物品系统
        public SubsystemAudio m_subsystemAudio;            // 音频系统
        public Random m_random = new Random();             // 随机数生成器

        /// <summary>
        /// 连锁处理状态 - 记录当前连锁过程的状态
        /// </summary>
        private class ChainProcessState
        {
            public HashSet<Vector3> ProcessingBlocks = new HashSet<Vector3>(); // 正在处理的方块位置集合
            public Queue<BlockProcessInfo> PendingBlocks = new Queue<BlockProcessInfo>(); // 待处理方块队列
            public float TimeSinceLastProcess = 0;         // 距离上次处理的时间间隔
        }

        private List<ChainProcessState> m_activeChains = new List<ChainProcessState>(); // 当前活动的连锁列表

        private const float PROCESS_INTERVAL = 0.06f;      // 每次连锁处理的时间间隔(秒)

        /// <summary>
        /// 方块掉落配置表 - 键为方块ID，值为掉落信息
        /// </summary>
        private Dictionary<int, BlockDropInfo> blockDrops = new Dictionary<int, BlockDropInfo>()
        {
            // 格式：{ 方块ID, new BlockDropInfo(主掉落ID, 主掉落数量, [次掉落ID, 次掉落数量]) }
            {9, new BlockDropInfo(9, 1)},                  // 橡木(OakWoodBlock) -> 橡木×1
            {10, new BlockDropInfo(10, 1)},                // 桦木(BirchWoodBlock) -> 桦木×1
            {11, new BlockDropInfo(11, 1)},                // 云杉木(SpruceWoodBlock) -> 云杉木×1
            {16, new BlockDropInfo(22, 3, 248, 1)},         // 煤矿石(CoalOreBlock) -> 煤(CoalChunkBlock)×3 + 经验球×1
            {39, new BlockDropInfo(249, 2, 248, 1)},        // 铜矿石(CopperOreBlock) -> 铜矿块(IronOreChunkBlock)×2 + 经验球×1
            {41, new BlockDropInfo(43, 3, 248, 1)},         // 铁矿石(IronOreBlock) -> 孔雀石(MalachiteChunkBlock)×3 + 经验球×1
            {100, new BlockDropInfo(102, 2, 248, 1)},       // 硝石矿(SaltpeterOreBlock) -> 硝石块(SaltpeterChunkBlock)×2 + 经验球×1
            {101, new BlockDropInfo(103, 3, 248, 1)},       // 硫矿石(SulphurOreBlock) -> 硫块(SulphurChunkBlock)×3 + 经验球×1
            {112, new BlockDropInfo(111, 2, 248, 3)},       // 钻石矿(DiamondOreBlock) -> 钻石块(DiamondChunkBlock)×2 + 经验球×3
            {148, new BlockDropInfo(250, 2, 248, 1)},       // 锗矿石(GermaniumOreBlock) -> 锗矿块(GermaniumOreChunkBlock)×2 + 经验球×1
            {255, new BlockDropInfo(255, 1)},               // 红木(保留ID) -> 红木×1
            {262, new BlockDropInfo(262, 1)}                // 杨树木(PoplarWoodBlock) -> 杨树木×1
        };

        // 木质方块ID集合（连锁半径为1）
        private HashSet<int> woodBlocks = new HashSet<int> {
            9,   // 橡木(OakWoodBlock)
            10,  // 桦木(BirchWoodBlock)
            11,  // 云杉木(SpruceWoodBlock)
            255, // 红木(保留ID)
            262  // 杨树木(PoplarWoodBlock)
        };

        // 本系统处理的方块ID列表
        public override int[] HandledBlocks => new int[] {
            9, 10, 11,   // 橡木/桦木/云杉木
            16,           // 煤矿石
            39, 41,       // 铜矿石/铁矿石
            100, 101,     // 硝石矿/硫矿石
            112,         // 钻石矿
            148,         // 锗矿石
            255, 262     // 红木/杨树木
        };

        public UpdateOrder UpdateOrder => UpdateOrder.Default; // 使用默认更新顺序

        /// <summary>
        /// 初始化加载子系统
        /// </summary>
        public override void Load(ValuesDictionary valuesDictionary)
        {
            // 获取所需子系统
            m_subsystemTime = Project.FindSubsystem<SubsystemTime>(throwOnError: true);
            m_subsystemGameInfo = Project.FindSubsystem<SubsystemGameInfo>(throwOnError: true);
            m_subsystemPickables = Project.FindSubsystem<SubsystemPickables>(throwOnError: true);
            m_subsystemAudio = Project.FindSubsystem<SubsystemAudio>(throwOnError: true);
            base.Load(valuesDictionary);
        }

        /// <summary>
        /// 当方块被破坏时触发连锁采集
        /// </summary>
        public override void OnBlockRemoved(int value, int newValue, int x, int y, int z)
        {
            int blockID = Terrain.ExtractContents(value);
            var point = new Point3(x, y, z);

            // 只处理非连锁触发的方块破坏
            if (!m_processedPoints.Contains(point))
            {
                StartNewChain(x, y, z, blockID);
            }
        }

        /// <summary>
        /// 游戏每帧更新处理
        /// </summary>
        public void Update(float dt)
        {
            List<ChainProcessState> completedChains = new List<ChainProcessState>();

            // 处理所有活动中的连锁
            foreach (var chain in m_activeChains)
            {
                chain.TimeSinceLastProcess += dt;

                // 达到处理间隔且有待处理方块
                if (chain.TimeSinceLastProcess >= PROCESS_INTERVAL && chain.PendingBlocks.Count > 0)
                {
                    chain.TimeSinceLastProcess = 0;
                    BlockProcessInfo info = chain.PendingBlocks.Dequeue();
                    ProcessBlock(chain, info.X, info.Y, info.Z, info.BlockID); // 处理方块
                }

                // 检查是否已完成连锁
                if (chain.PendingBlocks.Count == 0)
                {
                    completedChains.Add(chain);
                }
            }

            // 移除已完成的连锁
            foreach (var chain in completedChains)
            {
                m_activeChains.Remove(chain);
            }
        }

        public override void OnPoll(int value, int x, int y, int z, int pollPass) { } // 空实现

        /// <summary>
        /// 开始新的连锁处理
        /// </summary>
        private void StartNewChain(int x, int y, int z, int blockID)
        {
            var chain = new ChainProcessState();
            chain.PendingBlocks.Enqueue(new BlockProcessInfo(x, y, z, blockID)); // 加入初始方块
            m_activeChains.Add(chain);                       // 添加到活动列表
        }

        /// <summary>
        /// 添加方块到连锁处理队列
        /// </summary>
        private void AddToChain(ChainProcessState chain, int x, int y, int z, int blockID)
        {
            Vector3 pos = new Vector3(x, y, z);

            // 避免重复处理
            if (!chain.ProcessingBlocks.Add(pos))
            {
                return;
            }

            chain.PendingBlocks.Enqueue(new BlockProcessInfo(x, y, z, blockID));
        }
        // 新增：用于跟踪正在被连锁处理的方块坐标
        private HashSet<Point3> m_processedPoints = new HashSet<Point3>();
        /// <summary>
        /// 处理单个方块的连锁效果
        /// </summary>
        /// <summary>
        /// 处理单个方块的连锁效果
        /// </summary>
        private void ProcessBlock(ChainProcessState chain, int centerX, int centerY, int centerZ, int blockID)
        {
            try
            {
                // 标记当前方块为已处理
                var centerPoint = new Point3(centerX, centerY, centerZ);
                m_processedPoints.Add(centerPoint);

                // 确定连锁半径：木质方块为1，其他为2
                int radius = woodBlocks.Contains(blockID) ? 1 : 2;

                // 遍历周围方块
                for (int xOffset = -radius; xOffset <= radius; xOffset++)
                {
                    for (int yOffset = -radius; yOffset <= radius; yOffset++)
                    {
                        for (int zOffset = -radius; zOffset <= radius; zOffset++)
                        {
                            int x = centerX + xOffset;
                            int y = centerY + yOffset;
                            int z = centerZ + zOffset;

                            Vector3 currentPos = new Vector3(x, y, z);

                            // 跳过已处理的方块
                            if (chain.ProcessingBlocks.Contains(currentPos))
                            {
                                continue;
                            }

                            int cellValue = SubsystemTerrain.Terrain.GetCellValue(x, y, z);
                            int neighborBlockID = Terrain.ExtractContents(cellValue);

                            // 如果是同类方块且有掉落配置
                            if (neighborBlockID == blockID && blockDrops.ContainsKey(blockID))
                            {
                                var dropInfo = blockDrops[blockID];

                                // 自定义方块破坏逻辑
                                SubsystemTerrain.DestroyCell(0, x, y, z, 0, true, true); // 破坏方块，禁止默认掉落

                                // 生成主掉落物
                                m_subsystemPickables.AddPickable(
                                    dropInfo.Drop1ID,
                                    dropInfo.Drop1Count,
                                    new Vector3(x + 0.5f, y + 0.5f, z + 0.5f),
                                    null,
                                    null
                                );

                                // 生成次掉落物（如果有）
                                if (dropInfo.HasSecondDrop)
                                {
                                    m_subsystemPickables.AddPickable(
                                        dropInfo.Drop2ID,
                                        dropInfo.Drop2Count,
                                        new Vector3(x + 0.5f, y + 0.5f, z + 0.5f),
                                        null,
                                        null
                                    );
                                }

                                // 播放音效：木质和石质不同音效
                                string soundName = woodBlocks.Contains(blockID) ?
                                    "Audio/Impacts/Wood/ImpactWood2" :
                                    "Audio/Impacts/Stone/ImpactStone3";

                                m_subsystemAudio.PlaySound(soundName, 1f, 0f, new Vector3(x, y, z), 9f, true);

                                // 将该方块加入连锁
                                AddToChain(chain, x, y, z, blockID);
                            }
                        }
                    }
                }
            }
            finally
            {
                // 从处理集合中移除当前方块
                chain.ProcessingBlocks.Remove(new Vector3(centerX, centerY, centerZ));
            }
        }

        /// <summary>
        /// 方块掉落信息类
        /// </summary>
        private class BlockDropInfo
        {
            public int Drop1ID { get; set; }       // 主掉落物ID
            public int Drop1Count { get; set; }      // 主掉落物数量
            public int Drop2ID { get; set; }        // 次掉落物ID
            public int Drop2Count { get; set; }      // 次掉落物数量
            public bool HasSecondDrop { get; set; }  // 是否有次掉落物

            public BlockDropInfo(int drop1Id, int drop1Count, int drop2Id = 0, int drop2Count = 0)
            {
                Drop1ID = drop1Id;
                Drop1Count = drop1Count;
                Drop2ID = drop2Id;
                Drop2Count = drop2Count;
                HasSecondDrop = drop2Id != 0;
            }
        }

        /// <summary>
        /// 方块处理信息类
        /// </summary>
        private class BlockProcessInfo
        {
            public int X { get; set; }      // 方块X坐标
            public int Y { get; set; }      // 方块Y坐标
            public int Z { get; set; }      // 方块Z坐标
            public int BlockID { get; set; } // 方块ID

            public BlockProcessInfo(int x, int y, int z, int blockId)
            {
                X = x;
                Y = y;
                Z = z;
                BlockID = blockId;
            }
        }
    }
}